//return 0 on fail. return result length on success (may truncate).  
//we consider '-1' as a dangerous return value that may cause a lot of bugs.  
//'buf' will always ended with '\0', and return value will always be length of the result.  
//it's safe to use like: len += safe_sprintf(buf+len, buf_size-len, fmt, ....)  
int safe_sprintf(char* buf, int buf_size, char* fmt, ...)  
                     __attribute__ ((__format__ (__printf__, 3, 4)));  


int safe_sprintf(char* buf, int buf_size, char* fmt, ...)  
{  
    if (buf == NULL || buf_size <= 0) {  
        return 0;  
    }  
  
    va_list ap;  
    va_start(ap, fmt);  
    int res = vsnprintf(buf, buf_size, fmt, ap);  
    va_end(ap);  
  
    if (res == -1) {  
        buf[0] = '\0';  
        return 0;  
    }  
  
    if (res >= buf_size) {  
        res = buf_size - 1;  
        buf[res] = '\0';  
    }  
  
    return res;  
} 